home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power CD-ROM!! 8
/
Power CD-ROM 8.iso
/
prgmming
/
oldutil
/
fmat.pas
< prev
next >
Wrap
Pascal/Delphi Source File
|
1994-12-10
|
16KB
|
488 lines
{
Demonstrates formatting a floppy disk from Turbo Pascal.
This version only formats DSDD 9 sector floppies (360KB).
Works with DOS 2.0 or 3.0 in either 360K or 1.2M drives.
Does not support a /S option.
Supports a /N or -N option that turns off the verify after format.
Turn off verify step and obtain a 2x speedup vs. DOS format.
Requires Turbo version 3.0 to compile. Compile with Minheap=Maxheap=$200.
Requires a cloning procedure after being compiled to a .COM file.
The cloning procedure copies the boot sector of an already-formatted
floppy into the program, where it can be used thereafter. To clone,
call the program as follows:
FMAT @ <enter>
Written 10/26/85. Kim Kokkonen, TurboPower Software.
Compuserve 72457,2131. (408)-378-3672.
}
PROGRAM fmat;
{-format a disk, DSDD 9 sectors per track only}
TYPE
{holds sector data during sector setup after formatting}
SectorBuffer = ARRAY[1..512] OF Char;
{same size as sector buffer but easily initialized in code segment}
FakeSectorBuffer = RECORD
l, h : STRING[255];
END;
FormatRecord = RECORD
cyl, hed, rec, num : Byte;
END;
FormatArray = ARRAY[1..18] OF FormatRecord;
DiskBaseRec = RECORD
unk1, unk2, mtr, bps, eot, gpl,
dtl, glf, fbf, hst, mst : Byte;
END;
DiskBasePtr = ^DiskBaseRec;
registers = RECORD
CASE Integer OF
1 : (ax, bx, cx, dx, bp, si, di, ds, es, flags : Integer);
2 : (al, ah, bl, bh, cl, ch, dl, dh : Byte);
END;
FATtable = ARRAY[0..1023] OF Byte;
CONST
{bootrecord is customized after the .COM file is created.
call FMAT with a single command line parameter '@' as follows:
FMAT @ <Enter>. This will fill in bootrecord with a real boot record}
BootRecord : FakeSectorBuffer = {fill in with bootrecord}
(l : ''; h : '');
VAR
reg : registers;
SB : SectorBuffer; {will fill in with dir sectors}
BR : SectorBuffer ABSOLUTE BootRecord;
VB : ARRAY[1..9] OF SectorBuffer; {will use for fast verify}
FMT : FormatArray;
FAT : FATtable;
drName : STRING[2];
param : STRING[10];
drive, dType : Byte;
ch : Char;
doVerify : Boolean;
BiosDiskBase : DiskBasePtr ABSOLUTE 0 : $78;
OldDiskBase : DiskBasePtr;
i, error : Integer;
tavail : Integer;
bavail : Real;
PROCEDURE BIOSreadSectors(funct, drive : Byte;
sector, track, head : Integer;
sects : Integer;
VAR buffer;
VAR error : Integer);
{-execute int 13 to read disk or verify via BIOS at low level}
BEGIN
reg.ax := (funct SHL 8) OR sects;
reg.dl := drive;
reg.dh := head;
reg.ch := track AND 255;
reg.cl := (sector AND 63) OR ((track SHR 8) SHL 6);
reg.es := Seg(buffer);
reg.bx := Ofs(buffer);
Intr($13, reg);
IF Odd(reg.flags AND 1) THEN
error := reg.ax SHR 8
ELSE
error := 0;
END {biosreadsectors} ;
PROCEDURE BIOSwriteSectors(drive : Byte;
sector, track, head : Integer;
sects : Integer;
VAR buffer : SectorBuffer;
VAR error : Integer);
{-execute int 13 to write disk via BIOS at low level}
BEGIN
reg.ax := $300 OR sects;
reg.dl := drive;
reg.dh := head;
reg.ch := track AND 255;
reg.cl := (sector AND 63) OR ((track SHR 8) SHL 6);
reg.es := Seg(buffer);
reg.bx := Ofs(buffer);
Intr($13, reg);
IF Odd(reg.flags AND 1) THEN BEGIN
error := reg.ax SHR 8;
WriteLn('error during format...');
Halt;
END ELSE
error := 0;
END {bioswritesectors} ;
PROCEDURE InitBoot;
{-self-customize this program to hold the boot record}
VAR
ch : Char;
error : Integer;
f : FILE;
tries : Byte;
FUNCTION CodeSize : Integer;
{thanks to Bob Tolz and Randy Forgaard for this function}
VAR
i : Byte;
BEGIN
i := 11;
WHILE NOT((Mem[DSeg-2 : i+3] <> $00E9) AND (MemW[DSeg-2 : i+4] = $0000)) AND
NOT((MemW[DSeg-2 : i+0] = $00E9) AND (MemW[DSeg-2 : i+2] = $E800)) DO
i := i+1;
CodeSize := ((((DSeg-2)-CSeg) SHL 4)+i+6)-$100
END {CodeSize} ;
BEGIN
WriteLn('You will now clone a copy of the boot record into this program...');
WriteLn('The completed version will be written to FMAT.COM');
Write('Place a DOS formatted disk in drive A: and press any key when ready ');
Read(Kbd, ch);
WriteLn;
{read the boot record}
tries := 0;
REPEAT
tries := Succ(tries);
BIOSreadSectors(2, 0, 1, 0, 0, 1, BR, error);
UNTIL (error = 0) OR (tries = 3);
IF error <> 0 THEN BEGIN
WriteLn('could not read boot record');
Halt;
END;
{clone this program}
Assign(f, 'FMAT.COM');
Rewrite(f, 1);
BlockWrite(f, Mem[CSeg : $100], CodeSize);
Close(f);
Halt;
END {initboot} ;
FUNCTION DOSversion : Byte;
{-return the major version number of DOS}
BEGIN
reg.ah := $30;
MsDos(reg);
DOSversion := reg.al;
END {dosversion} ;
FUNCTION ATmachine : Boolean;
{-return true if machine is AT class}
VAR
machtype : Byte ABSOLUTE $FFFF : $000E;
BEGIN
ATmachine := (machtype = $FC);
END {ATmachine} ;
PROCEDURE readDASD(drive : Byte; VAR dType : Byte);
{-read dasd for DOS 3}
{-whatever dasd is!}
BEGIN
reg.ah := $15;
reg.dl := drive;
Intr($13, reg);
IF Odd(reg.flags AND 1) THEN BEGIN
WriteLn('error reading DASD for format...');
Halt;
END;
dType := reg.ah;
END {readdasd} ;
PROCEDURE setDASD(drive, dType : Byte);
{-execute int 13 to "set DASD" for format of 360K disks on 1.2MB floppies}
VAR
tries : Byte;
BEGIN
tries := 0;
REPEAT
tries := Succ(tries);
reg.ah := $17;
reg.al := dType;
reg.dl := drive;
Intr($13, reg);
UNTIL (tries = 3) OR NOT(Odd(reg.flags AND 1));
IF Odd(reg.flags AND 1) THEN BEGIN
WriteLn('error setting DASD for format...');
Halt;
END;
END {setdasd} ;
PROCEDURE InitFAT;
{-initialize a FAT sector}
BEGIN
{fill fat with all zeros}
FillChar(FAT, 1024, 0);
{fill in the ID Bytes}
FAT[0] := $FD; {9 sector DSDD drive}
FAT[1] := $FF; {boilerplate}
FAT[2] := $FF;
tavail := 80;
END {initfat} ;
PROCEDURE InitDiskBase;
{-modify the disk base data per DOS 3 instructions}
BEGIN
{save old pointer}
OldDiskBase := BiosDiskBase;
{make a new disk base data area}
New(BiosDiskBase);
{put the data from the old area in the new one}
BiosDiskBase^ := OldDiskBase^;
{modify per dos 3 instructions, doesn't hurt on DOS 2}
BiosDiskBase^.glf := $50;
BiosDiskBase^.eot := 9;
END {initdiskbase} ;
PROCEDURE Format(drive : Byte; VAR FMT : FormatArray; VAR error : Integer);
{-lay down format tracks}
VAR
i : Integer;
BEGIN
{initialize format table}
FOR i := 1 TO 9 DO
WITH FMT[i] DO BEGIN
cyl := 0; {cylinder number, will fill in during format}
hed := 0; {head number}
rec := i; {sector number}
num := 2; {indicates 512 bytes per sector}
END;
FOR i := 1 TO 9 DO
WITH FMT[i+9] DO BEGIN
cyl := 0; {cylinder number, will fill in during format}
hed := 1; {head number}
rec := i; {sector number}
num := 2; {indicates 512 bytes per sector}
END;
{write the format information}
INLINE(
$8A/$56/$0C/ {MOV DL,[BP+0C] - get drive number}
$C4/$5E/$08/ {LES BX,[BP+08] - get pointer to format array}
$B9/$01/$00/ {MOV CX,0001 - track 0 sector 1}
{nexttrack: - loop over 40 disk tracks}
$8B/$FB/ {MOV DI,BX - index into format array}
$B0/$12/ {MOV AL,12 - number of sectors per track = 18}
{inittrack: - loop over 18 sectors per track}
$26/$88/$2D/ {MOV ES:[DI],CH - track track number in format array}
$81/$C7/$04/$00/ {ADD DI,0004}
$FE/$C8/ {DEC AL}
$75/$F5/ {JNZ inittrack}
$B6/$00/ {MOV DH,00 - format 9 sectors on side 0}
$B8/$01/$05/ {MOV AX,0501}
$CD/$13/ {INT 13}
$72/$18/ {JB error - check for errors}
$B6/$01/ {MOV DH,01 - format 9 sectors on side 1}
$B8/$01/$05/ {MOV AX,0501}
$53/ {PUSH BX}
$81/$C3/$24/$00/ {ADD BX,0024}
$CD/$13/ {INT 13}
$72/$0A/ {JB error - check for errors}
$5B/ {POP BX}
$FE/$C5/ {INC CH - next track}
$80/$FD/$28/ {CMP CH,28}
$75/$D2/ {JNZ nexttrack}
$31/$C0/ {XOR AX,AX - no errors, return 0}
{error:}
$C4/$7E/$04/ {LES DI,[BP+04]}
$26/$89/$05 {MOV ES:[DI],AX - return error code}
);
END {format} ;
PROCEDURE Verify(drive : Byte; VAR FAT : FATtable; VAR error : Integer);
{-verify that sectors were formatted}
VAR
t, h : Integer;
cluster, fatofs, topcluster, content : Integer;
BEGIN
{initialize the verify buffer - 9 sectors * 512 bytes}
FillChar(VB, 4608, $F6);
{verify all sectors}
FOR t := 0 TO 39 DO
FOR h := 0 TO 1 DO BEGIN
BIOSreadSectors(4, drive, 1, t, h, 9, VB, error);
IF error <> 0 THEN BEGIN
{mark the clusters on this track as unavailable}
cluster := ((9*(h+2*t)) DIV 2)-4;
topcluster := cluster+5;
WHILE cluster < topcluster DO BEGIN
fatofs := (3*cluster) DIV 2;
{get a word from the FAT}
Move(FAT[fatofs], content, 2);
{replace 12 bits of the word}
IF Odd(cluster) THEN
content := content OR $FF70
ELSE
content := content OR $0FF7;
{store it back}
Move(content, FAT[fatofs], 2);
cluster := Succ(cluster);
END;
{reduce the number of tracks available}
tavail := Pred(tavail);
END;
END;
END {verify} ;
PROCEDURE InitDIR;
{-initialize a sector for the root directory}
VAR
i : Integer;
BEGIN
{fill with format bytes}
FillChar(SB, 512, $F6);
{mark each directory entry as available}
FOR i := 1 TO 481 DO
IF ((i-1) MOD 32) = 0 THEN SB[i] := #0;
END {initdir} ;
BEGIN
doVerify := True;
{get the drive and doverify option}
IF ParamCount = 0 THEN BEGIN
Write('Enter drive to format: ');
ReadLn(drName);
END ELSE BEGIN
{read the command line parameters}
i := 1;
drName := '';
WHILE i <= ParamCount DO BEGIN
param := ParamStr(i);
CASE param[1] OF
'@' : InitBoot; {clone the boot record into this program}
'-', '/' : {check for options}
IF (Length(param) = 2) AND (UpCase(param[2]) = 'N') THEN
doVerify := False
ELSE
WriteLn('WARNING: unrecognized command line option ', param);
ELSE
drName := param;
END;
i := Succ(i);
END;
END;
{make sure the bootrecord has been cloned into program}
IF BR[1] = #0 THEN BEGIN
WriteLn('You must first clone a copy of the boot record');
WriteLn('into this program. Call as FMAT @ <Enter> to clone...');
Halt;
END;
{check for errors, should use DOS facilities to check non-removables}
IF (drName = '') OR NOT(UpCase(drName[1]) IN ['A', 'B']) THEN BEGIN
WriteLn('Drive not Specified or cannot be formatted');
Halt;
END;
REPEAT
{get BIOS drive number}
drive := Ord(UpCase(drName[1]))-65;
Write('Insert new disk in drive ', Chr(65+drive));
Write(' and press <Enter> to begin formatting ');
REPEAT
Read(Kbd, ch)
UNTIL (ch = ^M);
WriteLn;
IF ATmachine AND (DOSversion = 3) THEN BEGIN
{get the drive type, necessary when dealing with 1.2MB drives}
readDASD(drive, dType);
IF (dType = 0) OR (dType = 3) THEN BEGIN
WriteLn('Drive is not present or non-removable');
Halt;
END;
IF dType = 2 THEN
WriteLn('Formatting 360K floppy in 1.2MB drive');
{set the DASD type accordingly}
setDASD(drive, dType);
END;
Write('Formatting... ');
{set up the disk_base table}
InitDiskBase;
{lay down format tracks}
Format(drive, FMT, error);
{restore the disk_base table}
BiosDiskBase := OldDiskBase;
IF error <> 0 THEN BEGIN
WriteLn('Error during format...');
Halt;
END;
{initialize the FATtable}
InitFAT;
IF doVerify THEN BEGIN
{verify sectors}
Write('Verifying... ');
Verify(drive, FAT, error);
END;
IF error <> 0 THEN
WriteLn('Bad disk, format not verified...')
ELSE BEGIN
Write('Writing BOOT/FAT/DIR... ');
{write the boot record}
BIOSwriteSectors(drive, 1, 0, 0, 1, BR, error);
{write the FAT sectors}
Move(FAT[0], SB, 512);
BIOSwriteSectors(drive, 2, 0, 0, 1, SB, error);
Move(FAT[512], SB, 512);
BIOSwriteSectors(drive, 3, 0, 0, 1, SB, error);
Move(FAT[0], SB, 512);
BIOSwriteSectors(drive, 4, 0, 0, 1, SB, error);
Move(FAT[512], SB, 512);
BIOSwriteSectors(drive, 5, 0, 0, 1, SB, error);
{write the root directory}
InitDIR;
BIOSwriteSectors(drive, 6, 0, 0, 1, SB, error);
BIOSwriteSectors(drive, 7, 0, 0, 1, SB, error);
BIOSwriteSectors(drive, 8, 0, 0, 1, SB, error);
BIOSwriteSectors(drive, 9, 0, 0, 1, SB, error);
BIOSwriteSectors(drive, 1, 0, 1, 1, SB, error);
BIOSwriteSectors(drive, 2, 0, 1, 1, SB, error);
BIOSwriteSectors(drive, 3, 0, 1, 1, SB, error);
{calculate bytes available on disk}
{12 sectors are used by BOOT/FAT/DIR}
bavail := 512.0*(9.0*tavail-12.0);
WriteLn('Format complete'#7);
WriteLn('Bytes Available: ', bavail : 0 : 0);
END;
WriteLn;
Write('Format another? (Y/N) ');
REPEAT
Read(Kbd, ch);
ch := UpCase(ch);
UNTIL (ch IN ['Y', 'N']);
WriteLn(ch);
UNTIL ch = 'N';
END.